<script setup lang="ts">
import CsummarizeItem from "./CsummarizeItem.vue";
import { useInView } from "@@/hooks/toolsHooks";
import anime from "animejs";
import { type CSSProperties, type Component } from "vue";
import { BorderStyle } from "@@/components/types/index";

const { vInView } = useInView();

const props = withDefaults(
  defineProps<{
    lineHeight?: string;
    lineWidth?: string;
    borderColor?: string;
    borderWidth?: string;
    borderStyle?: BorderStyle;
    radius?: string;
  }>(),
  {
    lineHeight: "100rem",
    lineWidth: "200rem",
    borderColor: "var(--C-M1)",
    borderStyle: "solid",
    borderWidth: "2rem",
    radius: "var(--R-xxs)",
  }
);

const slot = useSlots();
type Item = InstanceType<typeof CsummarizeItem> & {
  type: any;
  children: Item[] | undefined;
};
function findItem(): Item[] {
  const res: Item[] = [];
  if (!slot.default) return res;
  let slots: Item[] | undefined = slot.default() as any;
  while (slots?.length) {
    const v = slots.shift()!;
    if (v.type === CsummarizeItem) res.push(v);
    else if (v.children) slots.push(...v.children);
  }
  return res;
}
const items = computed(() => findItem());

function ifClass(i: number) {
  if (items.value.length <= 1) return "colLine__center";
  if (i === 0) return "colLine__left";
  if (items.value.length - 1 === i) return "colLine__right";
  return "colLine__center";
}
function playAnimation(el: Element) {
  const mainLine = el.querySelector<HTMLDivElement>(
    ".Csummarize-line > .line"
  )!;
  const lineRows = el.querySelectorAll<HTMLDivElement>(
    ".Csummarize_item > .rowLine > .line"
  );
  const lineCols = el.querySelectorAll<HTMLDivElement>(
    ".Csummarize_item > .colLine > .line"
  );
  const contents = el.querySelectorAll<HTMLDivElement>(
    ".Csummarize_item > .content"
  );
  const mainInitStyle: CSSProperties = {
    transform: "scaleX(0)",
  };
  const rowInitStyle: CSSProperties = {
    transform: "scaleX(0)",
    "transform-origin": "0 0",
  };
  const colInitStyle: CSSProperties = {
    height: 0,
    opacity: "0",
  };
  const contentInitStyle: CSSProperties = {
    transform: "translateX(-100%)",
    opacity: "0",
  };
  Object.assign(mainLine.style, mainInitStyle);
  const timeLine = anime.timeline({
    duration: 300,
    easing: "cubicBezier(0,.50,.9,.88)",
  });
  timeLine.add({
    targets: mainLine,
    scaleX: 1,
  });
  lineRows.forEach((rowEl, index) => {
    const colEl = lineCols[index];
    const contentEl = contents[index];
    Object.assign(rowEl.style, rowInitStyle);
    Object.assign(colEl.style, colInitStyle);
    Object.assign(contentEl.style, contentInitStyle);
    timeLine
      .add(
        {
          targets: colEl,
          height: "100%",
          opacity: 1,
        },
        index === 0 ? "-=0" : "-=300"
      )
      .add(
        {
          targets: rowEl,
          scaleX: 1,
        },
        "-=200"
      )
      .add({
        targets: contentEl,
        translateX: 0,
        opacity: 1,
      });
  });
}
</script>

<template>
  <div
    v-in-view:once="(e) => playAnimation(e.target)"
    class="Csummarize"
    :style="{
      '--Csummarize-col': items.length * 2,
      '--Csummarize_item-line-H': props.lineHeight,
      '--Csummarize_item-line-W': props.lineWidth,
      '--Csummarize-borderColor': props.borderColor,
      '--Csummarize-borderStyle': props.borderStyle,
      '--Csummarize-borderWidth': props.borderWidth,
      '--Csummarize-radius': props.radius,
    }"
  >
    <div class="Csummarize-line">
      <div class="line"></div>
    </div>
    <div v-for="(item, i) in items" class="Csummarize_item">
      <div class="colLine" :class="ifClass(i)">
        <div class="line"></div>
      </div>
      <div class="rowLine">
        <div class="line"></div>
      </div>
      <component class="content" :is="item" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.Csummarize {
  display: grid;
  grid-template-columns: repeat(var(--Csummarize-col), 1fr);
  grid-template-rows: 0rem;
  --Csummarize-border: var(--Csummarize-borderStyle)
    var(--Csummarize-borderWidth) var(--Csummarize-borderColor);
}
.Csummarize-line {
  position: relative;
  left: calc(var(--Csummarize-radius) / 2);
  width: calc(100% - var(--Csummarize-radius));
  height: 0rem;
  grid-column: 2 / var(--Csummarize-col);
  .line {
    width: 100%;
    border-top: var(--Csummarize-border);
  }
}
.Csummarize_item {
  grid-column: span 2;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  .colLine {
    height: var(--Csummarize_item-line-H);
    .line {
      height: 100%;
    }
  }
  .colLine__center {
    width: 0;
    .line {
      border-left: var(--Csummarize-border);
    }
  }
  .colLine__right {
    .line {
      width: var(--Csummarize-radius);
      border-radius: 0 var(--Csummarize-radius) 0 0;
      border-right: var(--Csummarize-border);
      border-top: var(--Csummarize-border);
    }
  }
  .colLine__left {
    .line {
      width: var(--Csummarize-radius);
      border-radius: var(--Csummarize-radius) 0 0 0;
      border-left: var(--Csummarize-border);
      border-top: var(--Csummarize-border);
    }
  }
  .rowLine {
    .line {
      width: var(--Csummarize_item-line-W);
      border-top: var(--Csummarize-border);
    }
  }
}
</style>
